-- ********************************************
-- * Copyright (c) 2012 TPV R&D Center Brazil *
-- * All Rights Reserved                      *
-- ********************************************

--- toolkit.component.List

local List = Box:new()

function List:new(o)
   if (type(o) ~= 'table') then
      o = {}
   end

   local newList = Box:new(o)

   newList.parent = nil

   newList.componentType = "ListBase"

   newList.data = {}
   newList.boxFocus = nil

   newList.page = {
      intervalLeft = o.intervalLeft or 0,
      intervalTop = o.intervalTop or 0,
      updateFocused = false,
      hideScroll = false,
      lineSize = 1,
      linePosition = 1,
      columnSize = 1,
      columnPosition = 1
	}

   newList.nav = {
      selLine = 0,
      curLine = 1,
      lineLimit = 1,
      selColumn = 0,
      curColumn = 1,
      columnLimit = 1,
   }

   newList.scroll = {
      width = 6,
      color = {255, 255, 255, 200}
   }

   newList.scrollContent = nil
   newList.focusContent = nil
   newList.listContent = nil
   newList.firstContent = nil
   newList.lastContent = nil
   newList.listOrientation = 1

   newList.orientation = {
      vertical = 1,
      horizontal = 2,
   }

   newList.updateMode = {
      total = 1,
      partial = 2,
   }


   --generate an object
   setmetatable(newList, self)
   self.__index = self

   return newList
end

function List:setActive(bEnabled, bAvoidFlush)
   if (type(bEnabled) == 'boolean') then

      if (bEnabled ~= self.isActivated) then
         self.isActivated = bEnabled
         --update list
         self.parent:composeFocusContentBase(self)
         self.parent:updateListBase(self, true, true, bAvoidFlush)
      end
   end
end

function List:redraw(bAvoidFlush)
   self.parent:updateListBase(self, true, true, bAvoidFlush)
end

function List:getFocused()
   return self.data[self.nav.curLine][self.nav.curColumn]
end

function List:getCurrentPosition()
   return self.nav.curLine, self.nav.curColumn
end

function List:setFocused(nLine, nColumn)
   --set current line and column
   if (#self.nav.columnLimit > 0) then
      if (nLine > 0 and nLine <= self.nav.lineLimit) and
         (nColumn > 0 and nColumn <= self.nav.columnLimit[nLine]) then
         self.nav.curLine = nLine
         self.nav.curColumn = nColumn
      end
   end
end

function List:setSelected(nLine, nColumn)
   --set selected line and column
   if (#self.nav.columnLimit > 0) then
      if (nLine > 0 and nLine <= self.nav.lineLimit) and
         (nColumn > 0 and nColumn <= self.nav.columnLimit[nLine]) then
         self.nav.selLine = nLine
         self.nav.curLine = nLine
         self.nav.selColumn = nColumn
         self.nav.curColumn = nColumn
      end
   end
end

function List:setPage(o)
   if (type(o) == 'table') then
      self.page.lineSize = o.lineSize or self.page.lineSize
      self.page.columnSize = o.columnSize or self.page.columnSize
      self.page.updateFocused = o.updateFocused or self.page.updateFocused
      self.page.hideScroll = o.hideScroll or self.page.hideScroll
   end
end

function List:setData(o)
   if (type(o) == 'table') then
      self.dataIndex = o
   end
end

function List:addFocus(boxFocus)
   self.boxFocus = boxFocus or Box:new()
end

function List:addList(boxElement, tData)
   --set data
   if (type(tData) == 'table') then
      self.data = tData

      if (self.page.lineSize > 1) then
         self.nav.lineLimit = #self.data
      else
         self.nav.columnLimit = #self.data
      end
   end
   --set elements
   if (type(boxElement) == 'table') then
      if (boxElement.componentType == "Box") then
         self.children = boxElement
      end
   end
end

function List:moveUp()
   if (self.nav.lineLimit <= 1) then
      --do nothing
      return
   end

   local bUpdateMode = nil

   --remove focus
   self.parent:updateListBase(self, false)

   --check if first line
   if (self.nav.curLine == 1) then
      self.nav.curLine = self.nav.lineLimit
      self.page.linePosition = self.nav.lineLimit - self.page.lineSize + 1

      if (self.nav.lineLimit ~= self.page.lineSize) then
         bUpdateMode = self.updateMode.total
      end

   --check if inside page
   elseif (self.nav.curLine == self.page.linePosition) then
      self.nav.curLine = self.nav.curLine - 1
      self.page.linePosition = self.page.linePosition - 1

      bUpdateMode = self.updateMode.partial

   --inside page
   else
      self.nav.curLine = self.nav.curLine - 1
   end

   --update list
   self.parent:updateListBase(self, true, bUpdateMode)
end

function List:moveDown()
   if (self.nav.lineLimit <= 1) then
      --do nothing
      return
   end

   local bUpdateMode = nil

   --remove focus
   self.parent:updateListBase(self, false)

   --check if last line
   if (self.nav.curLine == self.nav.lineLimit) then
      self.nav.curLine = 1
      self.page.linePosition = 1

      if (self.nav.lineLimit ~= self.page.lineSize) then
         bUpdateMode = self.updateMode.total
      end

   --check if inside page
   elseif ((self.nav.curLine + 1) >= (self.page.linePosition + self.page.lineSize)) then
      self.nav.curLine = self.nav.curLine + 1
      self.page.linePosition = self.page.linePosition + 1

      bUpdateMode = self.updateMode.partial

   --inside page
   else
      self.nav.curLine = self.nav.curLine + 1
   end

   --update list
   self.parent:updateListBase(self, true, bUpdateMode)
end

function List:moveLeft()
   if (self.nav.columnLimit <= 1) then
      --do nothing
      return
   end

   local bUpdateMode = nil

   --remove focus
   self.parent:updateListBase(self, false)

   --check if first column
   if ((self.nav.curColumn - 1) < 1) then
      self.nav.curColumn = self.nav.columnLimit

      --check if inside page
      if (self.nav.columnLimit > self.page.columnSize) then
         self.page.columnPosition = self.nav.columnLimit - self.page.columnSize + 1

         bUpdateMode = self.updateMode.total
      end   

   --check if inside page
   elseif ((self.nav.curColumn - 1) < self.page.columnPosition) then
      self.nav.curColumn = self.nav.curColumn - 1
      self.page.columnPosition = self.page.columnPosition - 1

      bUpdateMode = self.updateMode.partial

   --inside page
   else
      self.nav.curColumn = self.nav.curColumn - 1
   end

   --update list
   self.parent:updateListBase(self, true, bUpdateMode)
end

function List:moveRight()
   if (self.nav.columnLimit <= 1) then
      --do nothing
      return
   end

   local bUpdateMode = nil

   --remove focus
   self.parent:updateListBase(self, false)

   --check if last column
   if ((self.nav.curColumn + 1) > self.nav.columnLimit) then
      self.nav.curColumn = 1

      --check if inside page
      if (self.nav.columnLimit > self.page.columnSize) then
         self.page.columnPosition = 1

         bUpdateMode = self.updateMode.total
      end

   --check if inside page
   elseif ((self.nav.curColumn + 1) >= (self.page.columnPosition + self.page.columnSize)) then
      self.nav.curColumn = self.nav.curColumn + 1
      self.page.columnPosition = self.page.columnPosition + 1

      bUpdateMode = self.updateMode.partial

   --inside page
   else
      self.nav.curColumn = self.nav.curColumn + 1
   end

   --update list
   self.parent:updateListBase(self, true, bUpdateMode)
end

function List:dispose()
   self.scrollContent = nil
   self.focusContent = nil
   self.listContent = nil
   self.firstContent = nil
   self.lastContent = nil
   collectgarbage()
end

return List
